home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / src / out-of-phase-102-c / OutOfPhase 1.02 Source / OutOfPhase Folder / Level 1 Extensions 29Sep94 / BufferedFileInput.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-23  |  11.2 KB  |  405 lines  |  [TEXT/KAHL]

  1. /* BufferedFileInput.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    System Dependency Library for Building Portable Software               */
  5. /*    Macintosh Version                                                      */
  6. /*    Written by Thomas R. Lawrence, 1993 - 1994.                            */
  7. /*                                                                           */
  8. /*    This file is Public Domain; it may be used for any purpose whatsoever  */
  9. /*    without restriction.                                                   */
  10. /*                                                                           */
  11. /*    This package is distributed in the hope that it will be useful,        */
  12. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  13. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                   */
  14. /*                                                                           */
  15. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  16. /*                                                                           */
  17. /*****************************************************************************/
  18.  
  19. #include "MiscInfo.h"
  20. #include "Audit.h"
  21. #include "Debug.h"
  22. #include "Definitions.h"
  23.  
  24. #include "BufferedFileInput.h"
  25. #include "Files.h"
  26. #include "Memory.h"
  27.  
  28.  
  29. #define BUFFERSIZE (4096) /* must be a power of two! */
  30. #define BUFFERMASK (BUFFERSIZE - 1)
  31.  
  32.  
  33. /* this structure is simple because we only handle sequential reading. */
  34. struct BufferedInputRec
  35.     {
  36.         FileType*                FileDescriptor;
  37.         long                        IndexIntoBuffer;
  38.         long                        IndexIntoFileOfStartOfBuffer;
  39.         long                        LengthOfFile;
  40.         MyBoolean                ErrorOcurredCantBeUsed;
  41.         char                        Buffer[BUFFERSIZE];
  42.     };
  43.  
  44.  
  45. static MyBoolean        FillBuffer(BufferedInputRec* BufferedThang)
  46.     {
  47.         long                            NumBytesToRead;
  48.  
  49.         CheckPtrExistence(BufferedThang);
  50.         ERROR(BufferedThang->ErrorOcurredCantBeUsed,PRERR(ForceAbort,
  51.             "FillBuffer:  error occurred and buffer can not be used"));
  52.         if (BufferedThang->IndexIntoFileOfStartOfBuffer + BUFFERSIZE
  53.             > BufferedThang->LengthOfFile)
  54.             {
  55.                 NumBytesToRead = BufferedThang->LengthOfFile
  56.                     - BufferedThang->IndexIntoFileOfStartOfBuffer;
  57.             }
  58.          else
  59.             {
  60.                 NumBytesToRead = BUFFERSIZE;
  61.             }
  62.         ERROR(GetFilePosition(BufferedThang->FileDescriptor)
  63.             != BufferedThang->IndexIntoFileOfStartOfBuffer,PRERR(ForceAbort,
  64.             "FillBuffer:  buffer index is out of sync with the file"));
  65.         if (0 != ReadFromFile(BufferedThang->FileDescriptor,&(BufferedThang->Buffer[0]),
  66.             NumBytesToRead))
  67.             {
  68.                 BufferedThang->ErrorOcurredCantBeUsed = True;
  69.                 return False;
  70.             }
  71.         return True;
  72.     }
  73.  
  74.  
  75. /* create a new buffered input object around a file.  the file is not allowed */
  76. /* to be tampered with after it has been registered with this since I am too */
  77. /* lazy to implement proper buffering in the Level 0 library like I should. */
  78. BufferedInputRec*        NewBufferedInput(struct FileType* TheFileDescriptor)
  79.     {
  80.         BufferedInputRec*    BufferedThang;
  81.         long                            FilePosition;
  82.  
  83.         CheckPtrExistence(TheFileDescriptor);
  84.  
  85.         BufferedThang = (BufferedInputRec*)AllocPtrCanFail(sizeof(BufferedInputRec),
  86.             "BufferedInputRec");
  87.         if (BufferedThang == NIL)
  88.             {
  89.              FailurePoint1:
  90.                 return NIL;
  91.             }
  92.  
  93.         BufferedThang->FileDescriptor = TheFileDescriptor;
  94.  
  95.         BufferedThang->LengthOfFile = GetFileLength(TheFileDescriptor);
  96.  
  97.         FilePosition = GetFilePosition(TheFileDescriptor);
  98.         BufferedThang->IndexIntoBuffer = FilePosition & BUFFERMASK;
  99.         BufferedThang->IndexIntoFileOfStartOfBuffer = FilePosition & (~BUFFERMASK);
  100.  
  101.         BufferedThang->ErrorOcurredCantBeUsed = False;
  102.  
  103.         if (!SetFilePosition(TheFileDescriptor,BufferedThang->IndexIntoFileOfStartOfBuffer))
  104.             {
  105.              FailurePoint2:
  106.                 ReleasePtr((char*)BufferedThang);
  107.                 goto FailurePoint1;
  108.             }
  109.         if (!FillBuffer(BufferedThang))
  110.             {
  111.              FailurePoint3:
  112.                 goto FailurePoint2;
  113.             }
  114.  
  115.         return BufferedThang;
  116.     }
  117.  
  118.  
  119. /* clean up a buffered input object from around a file.  the file may be */
  120. /* used normally after this has been called. */
  121. void                                EndBufferedInput(BufferedInputRec* BufferedThang)
  122.     {
  123.         CheckPtrExistence(BufferedThang);
  124.         if (!BufferedThang->ErrorOcurredCantBeUsed)
  125.             {
  126.                 (void)SetFilePosition(BufferedThang->FileDescriptor,
  127.                     BufferedThang->IndexIntoBuffer + BufferedThang->IndexIntoFileOfStartOfBuffer);
  128.             }
  129.         ReleasePtr((char*)BufferedThang);
  130.     }
  131.  
  132.  
  133. /* read a raw block of data from the file.  returns True if all went well or */
  134. /* False if some data could not be written to the file. */
  135. MyBoolean                        ReadBufferedInput(BufferedInputRec* BufferedThang,
  136.                                             long RequestedBytes, char* PlaceToPut)
  137.     {
  138.         CheckPtrExistence(BufferedThang);
  139.         ERROR(BufferedThang->ErrorOcurredCantBeUsed,PRERR(ForceAbort,
  140.             "ReadBufferedInput:  error ocurred, so buffer is no longer valid"));
  141.         ERROR(RequestedBytes < 0,PRERR(ForceAbort,
  142.             "ReadBufferedInput:  bad requested bytes"));
  143.  
  144.         /* do the read loop */
  145.         while (RequestedBytes > 0)
  146.             {
  147.                 if (BufferedThang->IndexIntoBuffer + BufferedThang->IndexIntoFileOfStartOfBuffer
  148.                     >= BufferedThang->LengthOfFile)
  149.                     {
  150.                         /* ran out of bytes, so we'll just tell them */
  151.                         BufferedThang->ErrorOcurredCantBeUsed = True;
  152.                         return False;
  153.                     }
  154.                 *PlaceToPut = BufferedThang->Buffer[BufferedThang->IndexIntoBuffer];
  155.                 BufferedThang->IndexIntoBuffer += 1;
  156.                 PlaceToPut += 1;
  157.                 RequestedBytes -= 1;
  158.                 if (BufferedThang->IndexIntoBuffer == BUFFERSIZE)
  159.                     {
  160.                         /* if we ran off the end of the file, then load increment internal indices */
  161.                         BufferedThang->IndexIntoBuffer = 0;
  162.                         BufferedThang->IndexIntoFileOfStartOfBuffer += BUFFERSIZE;
  163.                         /* load the next block from the disk */
  164.                         if (!FillBuffer(BufferedThang))
  165.                             {
  166.                                 BufferedThang->ErrorOcurredCantBeUsed = True;
  167.                                 return False;
  168.                             }
  169.                     }
  170.             }
  171.  
  172.         return True;
  173.     }
  174.  
  175.  
  176. /* read in a signed (2's complement) character.  returns True if successful. */
  177. MyBoolean                        ReadBufferedSignedChar(BufferedInputRec* BufferedThang,
  178.                                             signed char* SignedCharOut)
  179.     {
  180.         char                            Buff[1];
  181.  
  182.         CheckPtrExistence(BufferedThang);
  183.         if (!ReadBufferedInput(BufferedThang,1,Buff))
  184.             {
  185.                 return False;
  186.             }
  187.         if ((Buff[0] & 0x80) != 0)
  188.             {
  189.                 *SignedCharOut = ~0x7f | (Buff[0] & 0x7f);
  190.             }
  191.          else
  192.             {
  193.                 *SignedCharOut = Buff[0] & 0x7f;
  194.             }
  195.         return True;
  196.     }
  197.  
  198.  
  199. /* read in an unsigned character.  returns True if successful. */
  200. MyBoolean                        ReadBufferedUnsignedChar(BufferedInputRec* BufferedThang,
  201.                                             unsigned char* UnsignedCharOut)
  202.     {
  203.         char                            Buff[1];
  204.  
  205.         CheckPtrExistence(BufferedThang);
  206.         if (!ReadBufferedInput(BufferedThang,1,Buff))
  207.             {
  208.                 return False;
  209.             }
  210.         *UnsignedCharOut = Buff[0] & 0xff;
  211.         return True;
  212.     }
  213.  
  214.  
  215. /* read in a signed (2's complement) 16-bit short little endian.  returns True if sucessful. */
  216. MyBoolean                        ReadBufferedSignedShortLittleEndian(BufferedInputRec* BufferedThang,
  217.                                             signed short* SignedShortOut)
  218.     {
  219.         char                            Buff[2];
  220.  
  221.         CheckPtrExistence(BufferedThang);
  222.         if (!ReadBufferedInput(BufferedThang,2,Buff))
  223.             {
  224.                 return False;
  225.             }
  226.         if ((Buff[1] & 0x80) != 0)
  227.             {
  228.                 *SignedShortOut
  229.                     = (0xff & Buff[0])
  230.                     | ((~0x7f | ((short)Buff[1] & 0x7f)) << 8);
  231.             }
  232.          else
  233.             {
  234.                 *SignedShortOut
  235.                     = (0xff & Buff[0])
  236.                     | (((short)Buff[1] & 0x7f) << 8);
  237.             }
  238.         return True;
  239.     }
  240.  
  241.  
  242. /* read in a signed (2's complement) 16-bit short big endian.  returns True if sucessful. */
  243. MyBoolean                        ReadBufferedSignedShortBigEndian(BufferedInputRec* BufferedThang,
  244.                                             signed short* SignedShortOut)
  245.     {
  246.         char                            Buff[2];
  247.  
  248.         CheckPtrExistence(BufferedThang);
  249.         if (!ReadBufferedInput(BufferedThang,2,Buff))
  250.             {
  251.                 return False;
  252.             }
  253.         if ((Buff[0] & 0x80) != 0)
  254.             {
  255.                 *SignedShortOut
  256.                     = (0xff & Buff[1])
  257.                     | ((~0x7f | ((short)Buff[0] & 0x7f)) << 8);
  258.             }
  259.          else
  260.             {
  261.                 *SignedShortOut
  262.                     = (0xff & Buff[1])
  263.                     | (((short)Buff[0] & 0x7f) << 8);
  264.             }
  265.         return True;
  266.     }
  267.  
  268.  
  269. /* read in an unsigned 16-bit short little endian.  returns True if successful. */
  270. MyBoolean                        ReadBufferedUnsignedShortLittleEndian(BufferedInputRec* BufferedThang,
  271.                                             unsigned short* UnsignedShortOut)
  272.     {
  273.         char                            Buff[2];
  274.  
  275.         CheckPtrExistence(BufferedThang);
  276.         if (!ReadBufferedInput(BufferedThang,2,Buff))
  277.             {
  278.                 return False;
  279.             }
  280.         *UnsignedShortOut
  281.             = (0xff & Buff[0])
  282.             | (((short)Buff[1] & 0xff) << 8);
  283.         return True;
  284.     }
  285.  
  286.  
  287. /* read in an unsigned 16-bit short big endian.  returns True if successful. */
  288. MyBoolean                        ReadBufferedUnsignedShortBigEndian(BufferedInputRec* BufferedThang,
  289.                                             unsigned short* UnsignedShortOut)
  290.     {
  291.         char                            Buff[2];
  292.  
  293.         CheckPtrExistence(BufferedThang);
  294.         if (!ReadBufferedInput(BufferedThang,2,Buff))
  295.             {
  296.                 return False;
  297.             }
  298.         *UnsignedShortOut
  299.             = (0xff & Buff[1])
  300.             | (((short)Buff[0] & 0xff) << 8);
  301.         return True;
  302.     }
  303.  
  304.  
  305. /* read in a signed (2's complement) 32-bit long little endian.  returns True if successful. */
  306. MyBoolean                        ReadBufferedSignedLongLittleEndian(BufferedInputRec* BufferedThang,
  307.                                             signed long* SignedLongOut)
  308.     {
  309.         char                            Buff[4];
  310.  
  311.         CheckPtrExistence(BufferedThang);
  312.         if (!ReadBufferedInput(BufferedThang,4,Buff))
  313.             {
  314.                 return False;
  315.             }
  316.         if ((Buff[3] & 0x80) != 0)
  317.             {
  318.                 *SignedLongOut
  319.                     = (0xff & Buff[0])
  320.                     | ((0xff & (long)Buff[1]) << 8)
  321.                     | ((0xff & (long)Buff[2]) << 16)
  322.                     | ((~0x7f | ((long)Buff[3] & 0x7f)) << 24);
  323.             }
  324.          else
  325.             {
  326.                 *SignedLongOut
  327.                     = (0xff & Buff[0])
  328.                     | ((0xff & (long)Buff[1]) << 8)
  329.                     | ((0xff & (long)Buff[2]) << 16)
  330.                     | (((long)Buff[3] & 0x7f) << 24);
  331.             }
  332.         return True;
  333.     }
  334.  
  335.  
  336. /* read in a signed (2's complement) 32-bit long big endian.  returns True if successful. */
  337. MyBoolean                        ReadBufferedSignedLongBigEndian(BufferedInputRec* BufferedThang,
  338.                                             signed long* SignedLongOut)
  339.     {
  340.         char                            Buff[4];
  341.  
  342.         CheckPtrExistence(BufferedThang);
  343.         if (!ReadBufferedInput(BufferedThang,4,Buff))
  344.             {
  345.                 return False;
  346.             }
  347.         if ((Buff[0] & 0x80) != 0)
  348.             {
  349.                 *SignedLongOut
  350.                     = (0xff & Buff[3])
  351.                     | ((0xff & (long)Buff[2]) << 8)
  352.                     | ((0xff & (long)Buff[1]) << 16)
  353.                     | ((~0x7f | ((long)Buff[0] & 0x7f)) << 24);
  354.             }
  355.          else
  356.             {
  357.                 *SignedLongOut
  358.                     = (0xff & Buff[3])
  359.                     | ((0xff & (long)Buff[2]) << 8)
  360.                     | ((0xff & (long)Buff[1]) << 16)
  361.                     | (((long)Buff[0] & 0x7f) << 24);
  362.             }
  363.         return True;
  364.     }
  365.  
  366.  
  367. /* read in an unsigned 32-bit long little endian.  returns True if successful. */
  368. MyBoolean                        ReadBufferedUnsignedLongLittleEndian(BufferedInputRec* BufferedThang,
  369.                                             unsigned long* UnsignedLongOut)
  370.     {
  371.         char                            Buff[4];
  372.  
  373.         CheckPtrExistence(BufferedThang);
  374.         if (!ReadBufferedInput(BufferedThang,4,Buff))
  375.             {
  376.                 return False;
  377.             }
  378.         *UnsignedLongOut
  379.             = (0xff & Buff[0])
  380.             | ((0xff & (long)Buff[1]) << 8)
  381.             | ((0xff & (long)Buff[2]) << 16)
  382.             | (((long)Buff[3] & 0xff) << 24);
  383.         return True;
  384.     }
  385.  
  386.  
  387. /* read in an unsigned 32-bit long big endian.  returns True if successful. */
  388. MyBoolean                        ReadBufferedUnsignedLongBigEndian(BufferedInputRec* BufferedThang,
  389.                                             unsigned long* UnsignedLongOut)
  390.     {
  391.         char                            Buff[4];
  392.  
  393.         CheckPtrExistence(BufferedThang);
  394.         if (!ReadBufferedInput(BufferedThang,4,Buff))
  395.             {
  396.                 return False;
  397.             }
  398.         *UnsignedLongOut
  399.             = (0xff & Buff[3])
  400.             | ((0xff & (long)Buff[2]) << 8)
  401.             | ((0xff & (long)Buff[1]) << 16)
  402.             | (((long)Buff[0] & 0xff) << 24);
  403.         return True;
  404.     }
  405.